import React, { useState, useRef, useEffect, forwardRef, useImperativeHandle } from 'react';
import { StyleSheet, View, Text, Animated, Easing, ViewStyle, TextStyle } from 'react-native';
import { px2dp, scale, statusBarHeight, tabHeight, height } from '~/utils/px2dp';

type PositionValue = 'top' | 'center' | 'bottom';

interface Option {
    content: React.ReactNode;
    layout?: PositionValue;
    duration?: number;
    callback?: () => void;
}

interface Props {
    style?: ViewStyle;
    textStyle?: TextStyle;
    fadeInDuration?: number;
    fadeOutDuration?: number;
    showDuration?: number;
}

export interface ToastRef {
    show: (option: Option) => void;
}

const Toast = forwardRef<ToastRef, Props>(
    ({ style, textStyle, fadeInDuration = 300, fadeOutDuration = 400, showDuration = 1800 }, ref) => {
        const [isShow, setIsShow] = useState(false);
        const [content, setContent] = useState<React.ReactNode>(null);
        const [positionValue, setPositionValue] = useState<PositionValue>('center');
        const opacity = useRef(new Animated.Value(1)).current;

        const show = (
            option: Option = {
                content: '',
            },
        ) => {
            const { layout = 'center', duration = showDuration, content, callback } = option;
            setPositionValue(layout);
            setContent(content);
            setIsShow(true);

            opacity.setValue(0);
            Animated.sequence([
                Animated.timing(opacity, {
                    toValue: 1,
                    duration: fadeInDuration,
                    easing: Easing.linear,
                    useNativeDriver: true,
                }),
                Animated.delay(duration),
                Animated.timing(opacity, {
                    toValue: 0,
                    duration: fadeOutDuration,
                    easing: Easing.linear,
                    useNativeDriver: true,
                }),
            ]).start(() => {
                setIsShow(false);
                setContent(null);
                if (typeof callback === 'function') {
                    callback();
                }
            });
        };

        useImperativeHandle(ref, () => ({
            show,
        }));

        let position;
        switch (positionValue) {
            case 'top':
                position = { top: px2dp(statusBarHeight + 300) };
                break;
            case 'center':
                position = { top: '46%' };
                break;
            case 'bottom':
                position = { bottom: px2dp(tabHeight + 100) };
                break;
        }

        const ToastView = isShow ? (
            <View style={[styles.container, position]} pointerEvents="none">
                <Animated.View style={[styles.toast, { opacity }, style]}>
                    {React.isValidElement(content) ? (
                        content
                    ) : (
                        <Text style={[styles.content, textStyle]} numberOfLines={4}>
                            {content}
                        </Text>
                    )}
                </Animated.View>
            </View>
        ) : null;

        return ToastView;
    },
);

const styles = StyleSheet.create({
    container: {
        position: 'absolute',
        left: 0,
        right: 0,
        zIndex: 10000,
        alignItems: 'center',
    },
    toast: {
        maxWidth: '70%',
        backgroundColor: 'rgba(0,0,0,0.8)',
        borderRadius: px2dp(10),
        paddingVertical: px2dp(16),
        paddingHorizontal: px2dp(20),
        alignItems: 'center',
        justifyContent: 'center',
    },
    content: {
        fontSize: scale(28),
        lineHeight: scale(48),
        color: '#fff',
        textAlign: 'center',
    },
});

export default Toast;
